<template>
  <el-dialog v-model="dialogVisible" title="编辑共享文档链接" width="50%" draggable>
    <div class="link-tree">
      <el-tree :data="linkTree" node-key="id" default-expand-all :expand-on-click-node="false">
        <template #default="{ node, data }">
          <span class="custom-tree-node">
            <span>
              <el-icon v-if="!data.children"><Document /></el-icon>
              <el-icon v-else><Folder /></el-icon>
              {{ node.label }}
            </span>
            <span v-if="!data.children">
              <el-input v-model="data.link" placeholder="请输入链接" size="small" style="width: 300px" />
              <el-button size="small" type="primary" bg link @click="saveSingleLink(data)">
                <el-icon><Check /></el-icon>保存
              </el-button>
            </span>
          </span>
        </template>
      </el-tree>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveAllChanges" :loading="saving" :disabled="!hasChanges">一键保存</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { saveLink, saveAllLinks, GetFileData } from "@/api/modules/upload";
import { Document, Folder, Check } from "@element-plus/icons-vue";

interface LinkNode {
  id: string;
  label: string;
  link?: string;
  children?: LinkNode[];
  path: string;
}

const dialogVisible = ref(false);
const saving = ref(false);
const linkTree = ref<LinkNode[]>([]);
const originalLinks = ref<any>({});

const hasChanges = computed(() => {
  return JSON.stringify(flattenTree(linkTree.value)) !== JSON.stringify(originalLinks.value);
});

const flattenTree = (tree: LinkNode[]): any => {
  const result: any = {};
  const flatten = (nodes: LinkNode[], prefix: string = "") => {
    nodes.forEach(node => {
      if (node.children) {
        flatten(node.children, prefix + node.label + ".");
      } else {
        result[prefix + node.label] = node.link || "";
      }
    });
  };
  flatten(tree);
  return result;
};

const buildTree = (data: any, parentPath: string = ""): LinkNode[] => {
  let id = 0;

  const buildNode = (obj: any, currentPath: string): LinkNode[] => {
    return Object.entries(obj).map(([key, value]) => {
      const nodePath = currentPath ? `${currentPath}.${key}` : key;
      const node: LinkNode = {
        id: (++id).toString(),
        label: key,
        path: nodePath
      };

      if (typeof value === "object") {
        node.children = buildNode(value, nodePath);
      } else {
        node.link = value as string;
      }

      return node;
    });
  };

  return buildNode(data, parentPath);
};

const saveSingleLink = async (data: LinkNode) => {
  console.log(`保存链接: ${data.path} = ${data.link}`);
  try {
    await saveLink({ path: data.path, link: data.link });
    ElMessage.success(`链接 "${data.path}" 已保存`);
  } catch (error) {
    ElMessage.error(`保存链接 "${data.path}" 失败`);
  }
};

const fetchData = async () => {
  try {
    const res = await GetFileData();
    originalLinks.value = res.data;
    linkTree.value = buildTree(res.data);
  } catch (error) {
    ElMessage.error("获取数据失败");
  }
};

const saveAllChanges = async () => {
  saving.value = true;
  try {
    const flattenedLinks = flattenTree(linkTree.value);
    await saveAllLinks(flattenedLinks);
    ElMessage.success("所有链接已更新");
    dialogVisible.value = false;
    await fetchData();
  } catch (error) {
    ElMessage.error("更新失败");
  } finally {
    saving.value = false;
  }
};

onMounted(fetchData);

const openDialog = async () => {
  await fetchData();
  dialogVisible.value = true;
};

defineExpose({ openDialog });
</script>

<style lang="scss" scoped>
.link-tree {
  max-height: 400px;
  overflow-y: auto;
}
.custom-tree-node {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: space-between;
  padding-right: 8px;
  font-size: 14px;
  .el-icon {
    margin-right: 8px;
  }
  .el-button {
    margin-left: 8px;
  }
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  .el-button {
    margin-left: 10px;
  }
}
</style>
